﻿import json

from django.contrib import admin
from django.conf.urls import url
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from django.http import HttpResponse
from django.shortcuts import render_to_response, get_object_or_404
from django.contrib.admin.util import (unquote)
from django.utils.translation import ugettext as _
from django.utils.encoding import force_text
from django.utils.text import capfirst
from django.utils.html import format_html
from django.core.urlresolvers import reverse
from django.core import serializers

from clients.models import *

IS_INLINE_POPUP_VAR = '_inline_popup'


class HiddenModel(admin.ModelAdmin):
    def get_model_perms(self, request):
        """
        Return empty perms dict thus hiding the model from admin index.
        """
        return {}


class ServiceParameterAdmin(HiddenModel):
    model = ServiceParameter


class PopupAwareModelAdmin(admin.ModelAdmin):
    def response_add(self, request, obj, post_url_continue=None):
        if IS_INLINE_POPUP_VAR in request.REQUEST:
            params = ['window']
            if 'group' in request.REQUEST:
                params.append("'%s'" % request.REQUEST['group'])
                model = self.model
                try:
                    serializers.get_serializer('my_json')
                except:
                    serializers.register_serializer('my_json', 'clients.json_serializers')
                params.append("%s[0]" % serializers.serialize('my_json', [obj, ]))

            return HttpResponse('<script>window.opener.dismissChangePopupWindow(%s);</script>' % ', '.join(params))

    def response_change(self, request, obj):
        if IS_INLINE_POPUP_VAR in request.REQUEST:
            params = ['window']
            if 'group' in request.REQUEST:
                params.append("'%s'" % request.REQUEST['group'])
                model = self.model
                try:
                    serializers.get_serializer('my_json')
                except:
                    serializers.register_serializer('my_json', 'clients.json_serializers')
                params.append("%s[0]" % serializers.serialize('my_json', [obj, ]))

            return HttpResponse('<script>window.opener.dismissChangePopupWindow(%s);</script>' % ', '.join(params))
        else:
            return super(PopupAwareModelAdmin, self).response_change(request, obj)

    def get_changeform_initial_data(self, request):
        initial = super(PopupAwareModelAdmin, self).get_changeform_initial_data(request)
        if ('lock' in request.REQUEST):
            lock = request.REQUEST['lock'].split('|')
            initial[lock[0]] = lock[1]
        return initial


class GtLinkModelAdmin(PopupAwareModelAdmin):
    def get_inline_formsets(self, request, formsets, inline_instances,
                            obj=None):
        default_formsets = super(GtLinkModelAdmin, self).get_inline_formsets(request, formsets, inline_instances, obj)
        if obj is None:
            for formset in default_formsets:
                if isinstance(formset.opts, CustomizedTabularInline):
                    formset.formset.max_num = 0
        return default_formsets


class GtLinkUserInline(admin.TabularInline):
    model = GtLinkUser
    can_delete = False


# Define a new User admin
class UserAdmin(UserAdmin):
    fieldsets = None
    fields = ['username', "password", 'email', 'last_login']
    readonly_fields = ['last_login']
    inlines = (GtLinkUserInline, )


class CustomizedTabularInline(admin.TabularInline):
    template = 'admin/readonly_inlines/tabular.html'

    def edit_link(self, instance):
        url = reverse('admin:%s_%s_change' % (instance._meta.app_label,
                                              instance._meta.model_name),
                      args=(instance.id,))
        id = "add_%s" % instance._meta.model_name
        classname = 'inline-edit-link'
        label = u'Редактировать'
        link = u'<a href="{}" id="%s" class="%s" onclick="return addChangePopupWindow(this)">%s</a>' % (
            id, classname, label)
        return format_html(link, url)

    edit_link.short_description = ''

    def get_fields(self, request, obj=None):
        if issubclass(self.model, InlineAwareModel):
            custom_fields = []
            try:
                settings = InlineSettings.objects.get(name=self.model._meta.verbose_name.title())
                custom_fields = list(settings.field_settings.filter(visible=True).values_list('name', flat=True))
            except:
                custom_fields = self.fields
            self.fields = custom_fields

        return ["edit_link"] + self.fields

    def get_readonly_fields(self, request, obj=None):
        return ["edit_link"] + self.fields


# Register your models here.
class OperationInline(admin.TabularInline):
    model = Operation
    readonly_fields = ['author']
    exclude = ['agreement_number', 'payment_id']
    extra = 0


class OperationInlineForAgreement(admin.TabularInline):
    model = Operation
    readonly_fields = ['client', 'author']
    exclude = ['agreement_number', 'payment_id']
    extra = 0


class BonusInline(admin.TabularInline):
    model = Bonus
    readonly_fields = ['author']
    extra = 0


class OperationAdmin(GtLinkModelAdmin):
    model = Operation
    list_display = ['name', 'client', 'agreement', 'agreement_number', 'amount', 'date', "from_payment_system"]
    list_filter = ['client', 'agreement']

    def get_readonly_fields(self, request, obj=None):
        return ["client", "author", "payment_id", 'agreement_number'] if obj \
            else ["author", "payment_id", 'agreement_number']

    def save_form(self, request, form, change):
        i = form.save(commit=False)
        if not i.author:
            i.author = request.user
        return i

    def change_view(self, request, object_id, form_url='', extra_context=None):
        if object_id:
            op = Operation.objects.get(pk=object_id)
            extra_context = {'client_id': op.client_id}
        return super(OperationAdmin, self).change_view(request, object_id, form_url, extra_context=extra_context)


class ServiceParameterValueInline(admin.TabularInline):
    model = ServiceParameterValue
    fields = ['parameter', 'value']
    #readonly_fields = ['parameter']
    extra = 0
    max_num = 0


class ServiceAdmin(GtLinkModelAdmin):
    model = Service
    list_display = ['template', 'client', 'agreement', 'status', 'zone', 'price', 'connection_type']
    inlines = [ServiceParameterValueInline]

    fieldsets = (
        (None, {
            'fields':
                ('template', 'status', 'zone', 'address', 'client', 'agreement', 'price', 'connection_type'),
        }),
        (u'Параметры подключения', {
            'classes':
                ("placeholder serviceparametervalue_set-group",),
            "fields": ()
        }),
        (None, {
            'fields': ('code_connect', 'code_disconnect', 'code_block', 'code_activate')
        })
    )

    def get_readonly_fields(self, request, obj=None):
        return ["client"] if obj else self.readonly_fields

    def change_view(self, request, object_id, form_url='', extra_context=None):
        if object_id:
            service = Service.objects.get(pk=object_id)
            extra_context = {'client_id': service.client_id}
        return super(ServiceAdmin, self).change_view(request, object_id, form_url, extra_context=extra_context)

    def history_view(self, request, object_id, extra_context=None):
        # First check if the user can see this history.
        model = self.model
        obj = get_object_or_404(model, pk=unquote(object_id))

        if not self.has_change_permission(request, obj):
            raise PermissionDenied

        # Then get the history for this object.
        opts = model._meta
        app_label = opts.app_label

        context = {
            'title': _('Change history: %s') % force_text(obj),
            'module_name': capfirst(force_text(opts.verbose_name_plural)),
            'object': obj,
            'app_label': app_label,
            'opts': opts,
            'changesets': obj.changesets.order_by("-date"),
            'preserved_filters': self.get_preserved_filters(request),
        }
        context.update(extra_context or {})

        return render_to_response('admin/clients/service/track.html', context)


class ServiceInline(CustomizedTabularInline):
    model = Service
    readonly_fields = ["client"]
    fields = ['template', 'status', 'zone', 'agreement', 'price', 'connection_type', 'code_connect', 'code_disconnect',
              'code_block', 'code_activate']
    extra = 0


class AgreementInline(CustomizedTabularInline):
    model = Agreement
    extra = 0


class AgreementAdmin(GtLinkModelAdmin):
    model = Agreement
    inlines = [OperationInlineForAgreement, ServiceInline]
    list_display = ["number", "client"]

    def get_readonly_fields(self, request, obj=None):
        read_only = super(AgreementAdmin, self).get_readonly_fields(request, obj)
        if obj:
            read_only = read_only + ("client",)
        return read_only

    def change_view(self, request, object_id, form_url='', extra_context=None):
        if object_id:
            agreement = Agreement.objects.get(pk=object_id)
            extra_context = {'client_id': agreement.client_id}
        return super(AgreementAdmin, self).change_view(request, object_id, form_url, extra_context=extra_context)

    def save_formset(self, request, form, formset, change):
        if formset.model == Operation or formset.model == Bonus:
            instances = formset.save(commit=False)
            for i in instances:
                if not i.author:
                    i.author = request.user
                if not i.client_id:
                    i.client = form.instance.client
                i.save()
            formset.save_m2m()
        elif formset.model == Service:
            instances = formset.save(commit=False)
            for i in instances:
                if not i.client_id:
                    i.client = form.instance.client
                i.save()
            formset.save_m2m()
        else:
            instances = formset.save()
        return instances


class ServicePriceAdmin(GtLinkModelAdmin):
    list_display = ["service", "zone", "amount", "created"]
    list_display_links = ["service"]
    readonly_fields = ["created"]


class ClientAdmin(GtLinkModelAdmin):
    inlines = [OperationInline, BonusInline, AgreementInline, ServiceInline]
    readonly_fields = ["balance", 'bonus_points']
    search_fields = ['name', 'phone', 'address']
    list_display = ["name", "phone", "address", "balance"]
    list_display_links = ["name"]
    fieldsets = ((u'Основное', {
        'fields':
            ('name', 'type', 'phone', 'email', 'comments', 'balance', 'bonus_points'),
        'classes': ( u'client-main',)
    }),
                 (u'Реквизиты', {
                     'fields':
                         ('passeria', 'pasnomer', 'paspodrazdelenie', 'pasdate', 'address'),
                     'classes': (u'client-properties-individual',)
                 }),
                 (u'Реквизиты', {
                     'fields':
                         ('inn', 'address'),
                     'classes': (u'client-properties-legal',)
                 }),
    )

    def save_formset(self, request, form, formset, change):
        if formset.model == Operation:
            instances = formset.save(commit=False)
            for i in instances:
                if not i.author:
                    i.author = request.user
                i.save()
            formset.save_m2m()
        else:
            instances = formset.save()
        return instances

    def change_view(self, request, object_id, form_url='', extra_context=None):
        extra_context = {'client_id': object_id}
        return super(ClientAdmin, self).change_view(request, object_id, form_url, extra_context=extra_context)


class InlineSettingsFieldInline(admin.TabularInline):
    model = InlineSettingsField
    readonly_fields = ['verbose']
    exclude = ['name']
    extra = 0

    def has_delete_permission(self, request, obj=None):
        return False

    def has_add_permission(self, request, obj=None):
        return False


class InlineSettingsAdmin(admin.ModelAdmin):
    model = InlineSettings
    readonly_fields = ['name']
    list_display = ['name', 'settings']
    inlines = [InlineSettingsFieldInline]


class GtLinkBillingAdmin(admin.AdminSite):
    def get_urls(self):
        urls = super(GtLinkBillingAdmin, self).get_urls()
        my_urls = [
            url(r'^get_price/(?P<service_id>[0-9]+)/(?P<zone_id>[0-9]+)/$', self.get_service_price, name='get_price'),
            url(r'^get_service_code/(?P<type>[0-9]+)/$', self.get_service_code, name='get_service_code'),
            url(r'^get_connection_type_parameters/(?P<type>[0-9]+)/$', self.get_connection_type_parameters,
                name='get_connection_type_parameters'),
            url(r'^get_client_agreements/(?P<client>[0-9]+)/$', self.get_client_agreements,
                name='get_client_agreements'),
        ]
        return my_urls + urls

    def get_service_price(self, request, service_id, zone_id):
        entries = Price.objects.filter(service=service_id, zone=zone_id).order_by('-created')
        return HttpResponse(entries[0].amount if entries else "", content_type="application/json")

    def get_service_code(self, request, type):
        try:
            con_type = ConnectionType.objects.get(pk=type)
            return HttpResponse(json.dumps({
                'connect': con_type.connect,
                'disconnect': con_type.disconnect,
                'activate': con_type.activate,
                'block': con_type.block}
            ), content_type="application/json")
        except Exception, e:
            return HttpResponse("")

    def get_client_agreements(self, request, client):
        try:
            client = Client.objects.get(pk=client)
            data = [{'id': a.id, 'number': a.number} for a in client.agreements.all()]
            return HttpResponse(json.dumps(data), content_type="application/json")
        except:
            return HttpResponse("")

    def get_connection_type_parameters(self, request, type):
        try:
            connection_type = ConnectionType.objects.get(pk=type)
            data = [{'id': p.id, 'name': p.name} for p in connection_type.parameters.all()]
            return HttpResponse(json.dumps(data), content_type="application/json")
        except:
            return HttpResponse("")


class ConnectionTypeAdmin(admin.ModelAdmin):
    model = ConnectionType
    filter_horizontal = ['parameters']


customized_site = GtLinkBillingAdmin()

customized_site.register(Client, ClientAdmin)
customized_site.register(Zone)
customized_site.register(Service, ServiceAdmin)
customized_site.register(Price, ServicePriceAdmin)
customized_site.register(ServiceTemplate)
customized_site.register(Agreement, AgreementAdmin)
customized_site.register(ConnectionType, ConnectionTypeAdmin)
customized_site.register(Operation, OperationAdmin)
customized_site.register(InlineSettings, InlineSettingsAdmin)
customized_site.register(ServiceParameter, ServiceParameterAdmin)
#
#customized_site.unregister(User)
customized_site.register(User, UserAdmin)